slider1:4<1,8,1>pattern steps per beat
slider2:0.9<0,1,0.01>pulse width
slider3:2<1,8,1>pattern beats
slider4:100<0,100,1>wet/dry mix

@init
ext_noinit = 1;
secondspersample = 1/srate;
// buffer locations
pattern_left = 0;
pattern_right = 128;
freembuf(257);
(loaded == 0) ?
(
// set up the default pattern
pattern_left[0] = 1;
pattern_left[2] = 1;
pattern_left[3] = 1;
pattern_left[6] = 1;
pattern_left[8] = 1;
pattern_left[10] = 1;
pattern_left[12] = 1;
pattern_left[14] = 1;   
pattern_right[0] = 1;
pattern_right[2] = 1;
pattern_right[3] = 1;
pattern_right[5] = 1;
pattern_right[8] = 1;
pattern_right[10] = 1;
pattern_right[13] = 1;
pattern_right[15] = 1;
);

@slider
pattern_steps_per_beat=slider1;
pulsewidth=slider2;
slew_rate = 1; // in ms, used to be a slider
delta = secondspersample / (slew_rate / 1000);
pattern_beats = slider3;
pattern_length = pattern_beats * pattern_steps_per_beat;
mix = slider4/100;

@block
samplesperbeat = srate/(tempo/60);
samplesperslice = samplesperbeat / pattern_steps_per_beat;

@sample
inL=spl0;
inR=spl1;

current_slice = (beat_position * pattern_steps_per_beat)|0;
current_slice = current_slice % pattern_length;
(current_slice != last_slice) ? current_pos = 0; // retrigger
last_slice = current_slice;
slice_vol_left = pattern_left[current_slice];
slice_vol_right = pattern_right[current_slice];

// truncate the pulses if pulsewidth < 0
(slice_vol_left) ? (current_pos % samplesperslice) > (samplesperslice * pulsewidth) ? slice_vol_left = 0;
(slice_vol_right) ? (current_pos % samplesperslice) > (samplesperslice * pulsewidth) ? slice_vol_right = 0;

(multiplier_left < slice_vol_left) ? multiplier_left = min(1,multiplier_left+delta):
(multiplier_left > slice_vol_left) ? multiplier_left = max(0,multiplier_left-delta);

(multiplier_right < slice_vol_right) ? multiplier_right = min(1,multiplier_right+delta):
(multiplier_right > slice_vol_right) ? multiplier_right = max(0,multiplier_right-delta);

spl0 = inL * multiplier_left * mix;
spl1 = inR * multiplier_right * mix;
spl0 += inL * (1-mix);
spl1 += inR * (1-mix);

current_pos += 1;

@serialize
// dump out entire left and right volume arrays
amt=file_mem(handle,pattern_left,128);
amt=file_mem(handle,pattern_right,128);
((file_avail(0) >= 0) & (amt > 0)) ?
(
loaded = 1;
);

@gfx 320 60
gslice = 0;
gspace = 10;
gstartx = gspace;
gheight = 15;
gwidthmax = (120 * pattern_beats) / pattern_length; //30;
gleft_y = gspace + gheight;
gcurrent_y = gspace * 2 + gleft_y;
gright_y = gspace + gcurrent_y + gheight;

// has the left mouse button been pressed or released?
(mouse_cap != leftbutton_down) ? 
(
leftbutton_down = (mouse_cap == 1) ? 1 : 0;
(leftbutton_down) ? 
(
(mouse_x >= gstartx && mouse_x < gstartx + pattern_length * gwidthmax) ?
(
mouse_slice = ((mouse_x - gstartx) / gwidthmax)|0;
(mouse_y >= gleft_y - gheight && mouse_y < gleft_y) ? 
(
pattern_left[mouse_slice] = pattern_left[mouse_slice] ? 0 : 1;
// slider5 += 1; sliderchange(slider5); // attempt to prompt js that state needs to be saved
);
(mouse_y >= gright_y - gheight && mouse_y < gright_y) ? 
(
pattern_right[mouse_slice] = pattern_right[mouse_slice] ? 0 : 1;
// slider5 += 1; sliderchange(slider5); // attempt to prompt js that state needs to be saved
);
);
);
);

// draw the pattern
gfx_a = 1;
gslice = 0;
loop (pattern_length,
gtestbit = pow(2,7-gslice)|0;
gslice_vol_left = pattern_left[gslice];
gslice_vol_right = pattern_right[gslice];
gwidth = gwidthmax * pulsewidth;

gfx_r = 0.0; // 1
gfx_b = 0.0; // 0.33
gfx_g = 0.33; // 1

gfx_x = gstartX + gslice * gwidthmax;
gfx_y = gleft_y;
gslice_vol_left ? gfx_rectto(gfx_x + gwidth, gfx_y - gheight) : gfx_lineto(gfx_x + gwidth, gfx_y, 0);

gfx_x = gstartX + gslice * gwidthmax;
gfx_y = gright_y;
gslice_vol_right ? gfx_rectto(gfx_x + gwidth, gfx_y - gheight) : gfx_lineto(gfx_x + gwidth, gfx_y, 0);

// draw the current slice marker
(current_slice == gslice) ? 
(
gfx_r = 0.33;
gfx_b = 1;
gfx_g = 0.33;

gfx_x = gstartX + gslice * gwidthmax;
gfx_y = gcurrent_y;
gfx_rectto(gfx_x + gwidth, gfx_y - gspace);
);

gslice +=1;
);

gslice = 0;
loop (pattern_beats + 1,
// draw beat markers
gfx_r = 0.5;
gfx_b = 0.5;
gfx_g = 0.5;

gfx_x = gstartX - 2 + gslice * gwidthmax * pattern_steps_per_beat;
gfx_y = gleft_y + 5;
gfx_lineto(gfx_x, gright_y - gheight - 5, 0);

gslice += 1;
);